# __getattr__(): 当访问对象属性时，如果属性不存在，那么会调用__getattr__()方法
class MyClass:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __getattr__(self, item):
        print("__getattr__()方法被调用")
        return "属性不存在"

obj = MyClass()
# a,b属性都存在，它不会访问__getattr__()方法
print(obj.a)
print(obj.b)
# c属性不存在，它会访问__getattr__()方法
print(obj.c)

print("=" * 50)
# __getattribute__(): 当访问对象属性时，都会调用__getattribute__()方法
class MyClass2:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __getattribute__(self, name):
        print("__getattribute__()方法被调用")
        print("访问的属性名:", name)
        # 调用父类的__getattribute__()方法
        # 如查我们在方法中直接self.name或obj.attr会再次的调用__getattribute__()方法，所以如果不调用父类的__getattribute__则会产生无限递归！！！
        return super().__getattribute__(name)

obj = MyClass2()
print(obj.a)
print(obj.b)
# c属性不存在，会报错：AttributeError: 'MyClass2' object has no attribute 'c'
# print(obj.c)

print("=" * 50)
# __setattr__(): 当设置对象属性时，会调用__setattr__()方法
class MyClass3:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __setattr__(self, name, value):
        print("__setattr__()方法被调用")
        print("设置的属性名:", name)
        print("设置的属性值:", value)
        # 调用父类的__setattr__()方法
        # 如查我们在方法中直接self.name或obj.attr会再次的调用__setattr__()方法，所以如果不调用父类的__setattr__则产生无限递归！！！
        return super().__setattr__(name, value)

obj = MyClass3()
obj.attr = "new_value"
print(obj.attr)

print("=" * 50)
# __delattr__(): 当删除对象属性时，会调用__delattr__()方法
class MyClass4:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __delattr__(self, name):
        print("__delattr__()方法被调用")
        print("删除的属性名:", name)
        # 调用父类的__delattr__()方法
        super().__delattr__(name)

obj = MyClass4()
del obj.a
# 在删除后再访问a属性则会报错：AttributeError: 'MyClass4' object has no attribute 'a'
# print(obj.a)


print("=" * 50)
# __dir__(): 这个方法用于返回对象的属性列表，在调用dir()函数时会调用它
class MyClass5:
    def __dir__(self):
        print("__dir__()方法被调用")
        return ['attr1','attr2','attr3']

obj = MyClass5()
print(dir(obj))